import socket
import threading


def broadcast(message, exclude_socket=None):
    """广播消息给所有客户端（排除指定发送者）"""
    # 使用列表副本防止遍历时修改原始列表
    clients_copy = clients.copy()

    disconnected_clients = []

    for client in clients_copy:
        try:
            if client["socket"] != exclude_socket:
                client["socket"].send(f"{message}".encode('utf-8'))
        except (ConnectionResetError, BrokenPipeError):
            print(f"客户端 {client['nickname']} 异常断开")
            disconnected_clients.append(client)

    # 清理已断开连接
    if disconnected_clients:
        for dc in disconnected_clients:
            if dc in clients:
                clients.remove(dc)
# 处理客户端请求的函数
def handle_client(client_socket, client_address, nickname):
    welcome_msg = f"system:{nickname} 进入了聊天室"
    print(welcome_msg)
    broadcast(welcome_msg)
    while True:
        try:
            message = client_socket.recv(1024).decode('utf-8')
            if message == 'exit':
                print(f"Connection with {client_address} closed.")
                break
            print(f"Message from {nickname}: {message}")
            # 格式化消息并广播
            formatted_msg = f"{nickname}: {message}"
            broadcast(formatted_msg, client_socket)
        except:
            break

    client_socket.close()


# 创建服务器端Socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
server_socket.bind(('192.168.145.234', 8080))
server_socket.listen(5)

clients = []

print("Server is running...")

while True:
    client_socket, client_address = server_socket.accept()
    nickname = client_socket.recv(1024).decode('utf-8').strip()
    if not nickname:
        nickname = f"匿名用户-{client_address[1]}"
    clients.append({"socket": client_socket, "nickname": nickname})


    #clients.append(client_socket)
    # 创建线程处理每个客户端
    client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address,nickname))
    client_thread.start()